import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { IBaseService } from '../00_base/IBaseService';
import { SysUser } from '../02_user/entities/user.entity';
import { JwtUtils } from './jwt.utils';
import { Result } from '../../common/result/Result';
import { ResultCode } from '../../common/result/ResultCode';
import { generator } from '../../common/utils/generator';
import * as svgCaptcha from 'svg-captcha';
import { JwtPayload } from './jwt.payload';

@Injectable()
export class AuthService {
  // 依赖配置注入
  constructor(
    @InjectRepository(SysUser)
    private usersRepository: Repository<SysUser>, // mysql数据库连接工具
    private jwt: JwtUtils, // 验签管理器（token）
    private baseService: IBaseService,
  ) {}

  // 登录
  async login(
    username: string,
    password: string,
    captchaKey: string,
    captchaCode: string,
  ) {
    const user = await this.findOneByUserNameAndPassword(
      username,
      generator.PasswordEncode(password),
    );
    if (user == null) {
      return Result.failed(ResultCode.USERNAME_OR_PASSWORD_ERROR);
    }
    const token = await this.jwt.generateToken(
      user,
      await this.getRoles(user.id),
      await this.getPerms(user.id),
    );
    await this.baseService.redisSetEX(user.id.toString(), token, 3600 * 8);
    const captchaTxt = await this.baseService.redisCaptchaGet(captchaKey); // 获取验证码用于验证
    if (captchaTxt == captchaCode) {
      return Result.success({
        accessToken: token,
        tokenType: 'Bearer',
        refreshToken: null,
        expires: null,
      });
    } else {
      return Result.failed(ResultCode.VERIFY_CODE_ERROR);
    }
  }

  async logout(payload: JwtPayload) {
    await this.baseService.redisSet(String(payload.userId), null);
  }

  // 根据用户名和密码查询账户信息
  findOneByUserNameAndPassword(
    username: string,
    password: string,
  ): Promise<SysUser | null> {
    return this.usersRepository.findOneBy({ username, password });
  }
  private async getRoles(userId: number): Promise<string[]> {
    const roles: [] = await this.usersRepository.query(
      `SELECT DISTINCT code FROM sys_role 
WHERE id IN (SELECT role_id FROM sys_user_role WHERE user_id = @0)`,
      [userId],
    );
    const res = [];
    roles.forEach((role) => {
      res.push(role['code']);
    });
    return res; // 修正了箭头函数的语法错误
  }
  private async getPerms(userId: number): Promise<string[]> {
    const perms: any[] = await this.usersRepository.query(
      `SELECT DISTINCT m.perm 
FROM sys_menu m 
INNER JOIN ( 
   SELECT DISTINCT menu_id 
   FROM sys_role_menu 
   INNER JOIN sys_user_role ON sys_role_menu.role_id = sys_user_role.role_id 
   WHERE sys_user_role.user_id = @0
) rm ON m.id = rm.menu_id 
WHERE perm IS NOT NULL;`,
      [userId],
    );
    const res = [];
    perms.forEach((perm) => {
      res.push(perm['perm']);
    });
    return res; // 修正了箭头函数的语法错误
  }

  async getCaptcha(): Promise<any> {
    const captcha = svgCaptcha.createMathExpr({
      mathMin: 1,
      mathMax: 9,
      noise: 1,
      color: true,
      width: 120,
      height: 40,
      fontSize: 30,
    });
    const svgData = captcha.data; // 获取SVG图像数据
    const captchaKey = generator.PrimaryKey();
    // 存储验证码的文字内容供后续验证
    await this.baseService.redisCaptchaSetEX(captchaKey, captcha.text, 10);
    // 将SVG数据转换为Base64格式
    const captchaBase64 = 'data:image/svg+xml;base64,' + btoa(svgData);
    return {
      captchaKey: captchaKey,
      captchaBase64: captchaBase64,
    };
  }
}
